/*

cimahis - Software para el analisis de imagenes de corte histologico

Copyright (C) Andrés De Abreu 2010 <jadabreu @ gmail . com>


Este programa es software libre. Puede redistribuirlo y/o modificarlo bajo los términos
de la Licencia Pública General de GNU según es publicada por la Free Software Foundation,
bien de la versión 2 de dicha Licencia o bien (según su elección) de cualquier versión
posterior.

Este programa se distribuye con la esperanza de que sea útil, pero SIN NINGUNA GARANTÍA,
incluso sin la garantía MERCANTIL implícita o sin garantizar la CONVENIENCIA PARA UN
PROPÓSITO PARTICULAR. Véase la Licencia Pública General de GNU para más detalles.

Debería haber recibido una copia de la Licencia Pública General junto con este programa.
Si no ha sido así, escriba a la Free Software Foundation, Inc.,
en 675 Mass Ave, Cambridge, MA 02139, EEUU.

    //ACERCA DE segmentacion.cpp
    *
    * Implementacion de la clase segmentacion la cual alberga los metodos de segmentacion
    * disponibles
    *

*/

#include "segmentacion.h"

segmentacion::segmentacion()
{
}

IplImage * segmentacion::vectorialRGB(IplImage *imagen, IplImage *imagenPatron)
{

    //metodo de segmentacion vectorial RGB tomado del libro de Gonzalez y Woods

        IplImage *r,*g,*b,*destino;
        fabricaObjetos f;
        histograma *hr,*hg,*hb;
        float mediaR,mediaG,mediaB,deR,deG,deB;
        float limiteInfR,limiteSupR,limiteInfG,limiteSupG,limiteInfB,limiteSupB;

        float factor=1.5;  //factor que amplia un poco el tamaño del cubo de segmentacion

        if (imagenPatron->nChannels==3)
        {
            r=obtenerCanal(imagenPatron,1);
            g=obtenerCanal(imagenPatron,2); //separar la imagen patron en canales
            b=obtenerCanal(imagenPatron,3);


            hr=f.crearHistograma("RGB");
            hg=f.crearHistograma("RGB"); //crear histogramas para cada canal
            hb=f.crearHistograma("RGB");

            hr->calcularHist(r);
            hg->calcularHist(g); //calcular histogramas
            hb->calcularHist(b);

            mediaR=hr->obtenerMedia();
            mediaG=hg->obtenerMedia(); //calculamos las medias de cada canal
            mediaB=hb->obtenerMedia();

            deR=hr->obtenerDesvEstandar();
            deG=hg->obtenerDesvEstandar(); //calculamos la desviacion estandar de cada canal
            deB=hb->obtenerDesvEstandar();

            limiteInfR=(mediaR-(factor*deR));
            limiteSupR=(mediaR+(factor*deR));

            limiteInfG=(mediaG-(factor*deG));  //calculamos el limite superior e inferior de cada canal dentro del "cubo" de segmentacion
            limiteSupG=(mediaG+(factor*deG));

            limiteInfB=(mediaB-(factor*deB));
            limiteSupB=(mediaB+(factor*deB));


        }
        if(imagen->nChannels==3)
        {
            cvReleaseImage(&r);
            cvReleaseImage(&g); //liberamos las variables para reutilizarlas
            cvReleaseImage(&b);

            r=obtenerCanal(imagen,1);
            g=obtenerCanal(imagen,2); //separamos la imagen a segmentar en canales
            b=obtenerCanal(imagen,3);

            double value1,value2,value3; //escalares donde se almacenara temporalmente los valores cuandos se recorre la imagen
            CvScalar blanco,negro; //escalares donde se guarda un pixel blanco y negro respectivamente
            blanco.val[0]=255;
            negro.val[0]=0;

            for (int i=0;i<r->height;i++)
            {
                for(int j=0;j<r->width;j++)
                {
                    value1=cvGetReal2D(r, i,j);
                    value2=cvGetReal2D(g, i,j);
                    value3=cvGetReal2D(b, i,j);

                    if(((value1<=limiteSupR)&&(value1>=limiteInfR))&&((value2<=limiteSupG)&&(value2>=limiteInfG))&&((value3<=limiteSupB)&&(value3>=limiteInfB)))
                    {
                        cvSet2D(r, i,j, negro);
                        cvSet2D(g, i,j, negro); //si los valores estan dentro de los limites.. cambiamos el pixel a negro
                        cvSet2D(b, i,j, negro);
                    }
                    else
                        {
                            cvSet2D(r, i,j, blanco);
                            cvSet2D(g, i,j, blanco); //si los valores estan fuera de los limites.. cambiamos el pixel a blanco
                            cvSet2D(b, i,j, blanco);
                        }

                }
            }



            destino=cvCreateImage(cvGetSize(imagen),8,3); //creamos la imagen resultante
            cvMerge(r,g,b,0,destino); //mezclamos los canales para generar la imagen resultante
            //cvSaveImage("destino1.jpg",destino);
            return destino;
        }
        return imagen;
}
